﻿/*
Copyright © 2011 Nokia Corporation. All rights reserved.
Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
Java and all Java-based marks are trademarks or registered trademarks of 
Sun Microsystems, Inc. Other product and company names mentioned herein may be 
trademarks or trade names of their respective owners.

Subject to the conditions below, you may, without charge:

·  Use, copy, modify and/or merge copies of this software and 
   associated content and documentation files (the “Software”)

·  Publish, distribute, sub-licence and/or sell new software 
   derived from or incorporating the Software.

Some of the documentation, content and/or software maybe licensed under open source software or other licenses.  To the extent such documentation, content and/or software are included, licenses and/or other terms and conditions shall apply in addition and/or instead of this notice. The exact terms of the licenses, disclaimers, acknowledgements and notices are reproduced in the materials provided.

This file, unmodified, shall be included with all copies or substantial portions
of the Software that are distributed in source code form.

The Software cannot constitute the primary value of any new software derived 
from or incorporating the Software.

Any person dealing with the Software shall not misrepresent the source of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;


using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Core;

using Carpool.Bing.Geocode;
using Carpool.Bing.Route;
using Carpool.Bing.Search;

using System.Device.Location;
using Microsoft.Phone.Controls.Maps.Platform;
using System.Globalization;

namespace Carpool
{
    public partial class RouteTool : UserControl, KarpoDialog
    {

        GeocodeServiceClient geocodeservice = new GeocodeServiceClient();
        RouteServiceClient routeservice = new RouteServiceClient();
        SearchServiceClient searchservice = new SearchServiceClient();

        //internal RouteModel routeModel = null;
        internal ICollection<GeoCoordinate> routeModel = null;
        MapPolyline routePolyline;
        MapLayer pushpinLayer;

        Canvas routeFromPinCanvas;
        Canvas routeToPinCanvas;
        Canvas routePickPinCanvas;
        Canvas routeFollowPinCanvas;
        Canvas routeFollowAliasCanvas;

        Image routeFromPin;
        Image routeToPin;
        Image routePickPin;
        Image routeFollowPin;
        TextBlock routeFollowAlias;

        internal DCRoutePoint fromRoute = null;
        internal DCRoutePoint toRoute = null;

        internal string routekarpoid = "0"; // if '0' then this is a new route
        internal string routecarpoolkarpoid = "0";
        internal string routekarponame = "";
        internal string routedescription = "";

        internal string routerepeat = "No repeat";
        internal string routetime = "";

        internal bool routeshowuserphone = false;
        internal bool routeshowusername = false;
        internal bool routeshowuserhometown = false;

        internal bool myownroute = true;

        internal string ownername = "NA";
        internal string ownerphone = "NA";
        internal string ownerhometown = "NA";


        static int ROUTETODO_FROM_POINT = 1;
        static int ROUTETODO_FROM_ADDRESS = 2;
        static int ROUTETODO_TO_POINT = 3;
        static int ROUTETODO_TO_ADDRESS = 3;
        int ROUTETODO = -1;

        public RouteTool()
        {
            InitializeComponent();

            routePolyline = new MapPolyline();
            pushpinLayer = new MapLayer();
            routeFromPinCanvas = new Canvas();
            routeToPinCanvas = new Canvas();
            routePickPinCanvas = new Canvas();
            routeFollowPinCanvas = new Canvas();
            routeFollowAliasCanvas = new Canvas();
            routeFromPin = new Image();
            routeToPin = new Image();
            routePickPin = new Image();
            routeFollowPin = new Image();

            routeFollowAlias = new TextBlock();
            routeFollowAlias.Margin = new Thickness(0);
            routeFollowAlias.Text = "";
            routeFollowAlias.TextAlignment = TextAlignment.Left;
            routeFollowAlias.VerticalAlignment = VerticalAlignment.Center;
            routeFollowAlias.HorizontalAlignment = HorizontalAlignment.Left;

            routeFollowAlias.FontFamily = new FontFamily("Arial");
            routeFollowAlias.FontSize = 24;
            routeFollowAlias.Foreground = new SolidColorBrush(Colors.Red);


            routeFromPin.Source = new BitmapImage(new Uri("icons/routestart.png", UriKind.Relative));
            routeToPin.Source = new BitmapImage(new Uri("icons/routeend.png", UriKind.Relative));
            routePickPin.Source = new BitmapImage(new Uri("icons/pickloc.png", UriKind.Relative));
            routeFollowPin.Source = new BitmapImage(new Uri("icons/driver.png", UriKind.Relative));


            routeFromPinCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(route_MouseLeftButtonUp);
            routeToPinCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(route_MouseLeftButtonUp);
            routePolyline.MouseLeftButtonUp += new MouseButtonEventHandler(route_MouseLeftButtonUp);

 
        }

        private void route_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            showRouteInfo();
        }

        private void routetoolPopup_Loaded(object sender, RoutedEventArgs e)
        {
            routePolyline.Stroke = new SolidColorBrush(Colors.Blue);
            routePolyline.StrokeThickness = 4;
            routePolyline.Opacity = 0.7;

            routeFromPinCanvas.Height = 34;
            routeFromPinCanvas.Width = 20;
            routeFromPinCanvas.Children.Add(routeFromPin);

            routeToPinCanvas.Height = 34;
            routeToPinCanvas.Width = 20;
            routeToPinCanvas.Children.Add(routeToPin);

            routePickPinCanvas.Height = 34;
            routePickPinCanvas.Width = 20;
            routePickPinCanvas.Children.Add(routePickPin);

            routeFollowPinCanvas.Height = 34;
            routeFollowPinCanvas.Width = 20;
            routeFollowPinCanvas.Children.Add(routeFollowPin);

            routeFollowAliasCanvas.Height = 34;
            routeFollowAlias.Width = 100;
            routeFollowAliasCanvas.Children.Add(routeFollowAlias);
            
            
        }

        private void routetoolPopup_Opened(object sender, EventArgs e)
        {

        }

        private void RouteTool_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            routeToolTranslateTransform.X += e.DeltaManipulation.Translation.X;
            routeToolTranslateTransform.Y += e.DeltaManipulation.Translation.Y;
        }

        public void showDialog(bool show)
        {
            routeToolTranslateTransform.X = 20.0;
            routeToolTranslateTransform.Y = 20.0;

            routetoolPopup.IsOpen = true;
            routeToolScaleStoryboard.Begin();

            clearCurrentRoute();


        }



        public void menuCommand(string command)
        {
            if (command == "Saved...")
            {
                MainPage.main.routeinfo.routeinfoPopup.IsOpen = false;
                MainPage.main.routedetails.routedetailsPopup.IsOpen = false;
                MainPage.main.addresssetting.show(false);

                clearCurrentRoute();

                MainPage.main.routeselection.loadRoutes();

                
            }
            else if (command == "New route...")
            {
                MainPage.main.addresssetting.show(false);
                clearCurrentRoute();
                
            }
            else if (command == "Back...")
            {
                clearCurrentRoute();
                MainPage.main.addresssetting.show(false);
                MainPage.main.resetMenu();
                routetoolPopup.IsOpen = false;
            }
        }

        internal void clearCurrentRoute()
        {
            clearMapObjects();
            fromRoute = null;
            toRoute = null;

            routekarpoid = "0"; // if '0' then this is a new route
            routecarpoolkarpoid = "0";
            routekarponame = "";
            routedescription = "";

            routerepeat = "No repeat";
            routetime = "";

            routeshowuserphone = MainPage.usershowphone;
            routeshowusername = MainPage.usershowname;
            routeshowuserhometown = MainPage.usershowhometown;

            myownroute = true;
            ownername = (routeshowusername ? MainPage.userfirstname + " " + MainPage.userlastname : "NA");
            ownerphone = (routeshowuserphone ? MainPage.userphone : "NA");
            ownerhometown = (routeshowuserhometown ? MainPage.userhometown : "NA");
        }

        internal void showRouteInfo()
        {
            if (fromRoute == null || toRoute == null)
            {
                KarpoMessageBox.showMessageBox("Set the start and end point first!");
            }
            else
            {
                MainPage.main.routeselection.routeselectionsPopup.IsOpen = false;
                MainPage.main.routedetails.routedetailsPopup.IsOpen = false;

                if (myownroute)
                {
                    ownername = (routeshowusername ? MainPage.userfirstname + " " + MainPage.userlastname : "NA");
                    ownerphone = (routeshowuserphone ? MainPage.userphone : "NA");
                    ownerhometown = (routeshowuserhometown ? MainPage.userhometown : "NA");

                } // else these privacy information is already set after the clerCurrentRoute is called 

                MainPage.main.routeinfo.setInfo(
                    fromRoute.latitude, fromRoute.longitude, fromRoute.street, fromRoute.postcode + " " + fromRoute.city, fromRoute.country,
                    toRoute.latitude, toRoute.longitude, toRoute.street, toRoute.postcode + " " + toRoute.city, toRoute.country,
                    toRoute.distance, secondToHMS(toRoute.traveltime),
                    routerepeat, routetime,
                    ownername, ownerhometown, ownerphone);
            }
        }
// -------------------------
        internal void addPushPin(Canvas pinCanvas, GeoCoordinate coords, Point point)
        {
            if (!MainPage.mainmap.Children.Contains(pushpinLayer))
            {
                MainPage.mainmap.Children.Add(pushpinLayer);
            }
            if (pushpinLayer.Children.Contains(pinCanvas))
            {
                pushpinLayer.Children.Remove(pinCanvas);
            }
            pushpinLayer.AddChild(pinCanvas, coords, point);
        }

        internal void showPickPin(double latitude, double longitude)
        {
            GeoCoordinate latlon = new GeoCoordinate(latitude, longitude);
            addPushPin(routePickPinCanvas, latlon, new Point(-10, -34));
        }

        internal void showDriverPin(double latitude, double longitude, bool center, string alias)
        {
            GeoCoordinate latlon = new GeoCoordinate(latitude, longitude);
            addPushPin(routeFollowPinCanvas, latlon, new Point(-10, -34));
            routeFollowAlias.Text = alias;
            addPushPin(routeFollowAliasCanvas, latlon, new Point(23, -34));

            if (center)
                MainPage.mainmap.Center = latlon;

        }

        internal void centerMapToCoordinates(double latitude, double longitude)
        {
            GeoCoordinate latlon = new GeoCoordinate(latitude, longitude);
            MainPage.mainmap.Center = latlon;
        }

        internal void clearMapObjects()
        {
            if (MainPage.mainmap.Children.Contains(routePolyline))
            {
                MainPage.mainmap.Children.Remove(routePolyline);
            }
            if (pushpinLayer.Children.Contains(routeFromPinCanvas))
            {
                pushpinLayer.Children.Remove(routeFromPinCanvas);
            }
            if (pushpinLayer.Children.Contains(routeToPinCanvas))
            {
                pushpinLayer.Children.Remove(routeToPinCanvas);
            }
            if (pushpinLayer.Children.Contains(routePickPinCanvas))
            {
                pushpinLayer.Children.Remove(routePickPinCanvas);
            } 
            if (pushpinLayer.Children.Contains(routeFollowPinCanvas))
            {
                pushpinLayer.Children.Remove(routeFollowPinCanvas);
            }
            if (pushpinLayer.Children.Contains(routeFollowAliasCanvas))
            {
                pushpinLayer.Children.Remove(routeFollowAliasCanvas);
            }
            MainPage.main.setFromToAddress(null, null);
            MainPage.main.showCrosshair(false);

        }



        // -------------------------------------------------------------------------------
        // --- FROM ----------------------------------------------------------------------
        // -------------------------------------------------------------------------------


        private void clearColor()
        {
            routeFrom.Background = MainPage.ButtonReleasedColor;
            routeFromPoint.Background = MainPage.ButtonReleasedColor;
            routeFromAddress.Background = MainPage.ButtonReleasedColor;
            routeTo.Background = MainPage.ButtonReleasedColor;
            routeToPoint.Background = MainPage.ButtonReleasedColor;
            routeToAddress.Background = MainPage.ButtonReleasedColor;

        }

        private void routeFrom_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor();
            routeFrom.Background = MainPage.ButtonPressedColorGreen;

            routeToPoint.Visibility = Visibility.Collapsed;
            routeToAddress.Visibility = Visibility.Collapsed;
        }

        private void routeFrom_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeFromPoint.Visibility = (routeFromPoint.Visibility==Visibility.Visible?Visibility.Collapsed:Visibility.Visible);
            routeFromAddress.Visibility = (routeFromAddress.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible);
        }

        private void routeFromPoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor();
            routeFrom.Background = MainPage.ButtonPressedColorGreen;
            routeFromPoint.Background = MainPage.ButtonPressedColorGreen;
        }

        private void routeFromPoint_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeFromPoint.Visibility = Visibility.Collapsed;
            routeFromAddress.Visibility = Visibility.Collapsed;
            ROUTETODO = RouteTool.ROUTETODO_FROM_POINT;
            MainPage.main.addresssetting.show(false);
            MainPage.main.showCrosshair(true);
        }

        private void routeFromAddress_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor();
            routeFrom.Background = MainPage.ButtonPressedColorGreen;
            routeFromAddress.Background = MainPage.ButtonPressedColorGreen;
        }

        private void routeFromAddress_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeFromPoint.Visibility = Visibility.Collapsed;
            routeFromAddress.Visibility = Visibility.Collapsed;
            ROUTETODO = RouteTool.ROUTETODO_FROM_ADDRESS;
            MainPage.main.showCrosshair(false);
            MainPage.main.addresssetting.show(true);
            
        }

        // -------------------------------------------------------------------------------
        // --- TO ------------------------------------------------------------------------
        // -------------------------------------------------------------------------------
        private void routeTo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor(); 
            routeTo.Background = MainPage.ButtonPressedColorGreen;
            routeFromPoint.Visibility = Visibility.Collapsed;
            routeFromAddress.Visibility = Visibility.Collapsed;
        }

        private void routeTo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeToPoint.Visibility = (routeToPoint.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible);
            routeToAddress.Visibility = (routeToAddress.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible);
        }

        private void routeToPoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor();
            routeTo.Background = MainPage.ButtonPressedColorGreen;
            routeToPoint.Background = MainPage.ButtonPressedColorGreen;
        }

        private void routeToPoint_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeToPoint.Visibility = Visibility.Collapsed;
            routeToAddress.Visibility = Visibility.Collapsed;
            ROUTETODO = RouteTool.ROUTETODO_TO_POINT;
            MainPage.main.addresssetting.show(false);
            MainPage.main.showCrosshair(true);
        }

        private void routeToAddress_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            clearColor();
            routeTo.Background = MainPage.ButtonPressedColorGreen;
            routeToAddress.Background = MainPage.ButtonPressedColorGreen;
        }

        private void routeToAddress_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeToPoint.Visibility = Visibility.Collapsed;
            routeToAddress.Visibility = Visibility.Collapsed;
            ROUTETODO = RouteTool.ROUTETODO_TO_ADDRESS;
            MainPage.main.showCrosshair(false);
            MainPage.main.addresssetting.show(true);
            
        }

        // -------------------------------------------------------------------------------
        // --- INFO ----------------------------------------------------------------------
        // -------------------------------------------------------------------------------
        private void routeInfo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            routeInfo.Background = MainPage.ButtonPressedColorGreen;
        }

        internal string secondToHMS(long traveltimeseconds)
        {
            long hourslong = (long)(traveltimeseconds / 3600);
            long minuteslong = (long)((traveltimeseconds - hourslong * 3600) / 60);
            long secondslong = (long)(traveltimeseconds - hourslong * 3600 - minuteslong * 60);
            string hours = String.Format("{0} h ", hourslong);
            string minutes = String.Format("{0} min ", minuteslong);
            string seconds = String.Format("{0} sec", secondslong);
            string traveltime = "";
            if (hourslong > 0)
                traveltime = hours;
            if (minuteslong > 0)
                traveltime += minutes;
            if (secondslong > 0)
                traveltime += seconds;

            return traveltime;
            
        }



        private void routeInfo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeInfo.Background = MainPage.ButtonReleasedColor;
            MainPage.main.addresssetting.show(false);
            showRouteInfo();
        }

        // -------------------------------------------------------------------------------
        // --- OK ------------------------------------------------------------------------
        // -------------------------------------------------------------------------------
        private void routeOk_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            routeOk.Background = MainPage.ButtonPressedColorGreen;
        }

        private void routeOk_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            routeOk.Background = MainPage.ButtonReleasedColor;
            if (fromRoute == null || toRoute == null)
            {
                KarpoMessageBox.showMessageBox("Set the start and end point first!");
            }
            else
            {
                MainPage.main.routeinfo.routeinfoPopup.IsOpen = false;
                MainPage.main.routeselection.routeselectionsPopup.IsOpen = false;

                MainPage.main.routedetails.init();
            }

        }




        // called when the crosshair is clicked,see MainPage.xaml.cs
        public void crosshairLocation(double lat, double lon)
        {
            //String latlon = "lat=" + lat + ", lon=" + lon;
            //MessageBox.Show(latlon);

            if (ROUTETODO == RouteTool.ROUTETODO_FROM_POINT)
            {
                fromRoute = new DCRoutePoint();
                fromRoute.type = "FROMPOINT";
                fromRoute.pointset = true;
                fromRoute.routepolyline = "[]";
                fromRoute.latitude = lat;
                fromRoute.longitude = lon;

                GeoCoordinate latlon = new GeoCoordinate(lat, lon);
                addPushPin(routeFromPinCanvas, latlon, new Point(-10, -34));

                SearchAddressForLatLon(lat, lon);

            }
            else if (ROUTETODO == RouteTool.ROUTETODO_TO_POINT)
            {
                toRoute = new DCRoutePoint();
                toRoute.type = "TOPOINT";
                toRoute.pointset = true;
                toRoute.routepolyline = "[]";
                toRoute.latitude = lat;
                toRoute.longitude = lon;

                GeoCoordinate latlon = new GeoCoordinate(lat, lon);
                addPushPin(routeToPinCanvas, latlon, new Point(-10, -34));

                SearchAddressForLatLon(lat, lon);

            }
        }


        internal void SearchLatLonForAddress(string street, string city, string country)
        {
            KarpoMessageBox.showMessageBox("Searching the point ...");

            GeocodeServiceClient geocodeClient = new GeocodeServiceClient();
            geocodeClient.GeocodeCompleted += new EventHandler<GeocodeCompletedEventArgs>(client_GeocodeCompleted);

            GeocodeRequest request = new GeocodeRequest();
            request.Culture = CultureInfo.CurrentUICulture.Name;

            request.Query = street + "," + city + "," + country;

            if (ROUTETODO == RouteTool.ROUTETODO_FROM_ADDRESS)
            {
                fromRoute = new DCRoutePoint();
                fromRoute.street = street;
                fromRoute.city = city;
                fromRoute.country = country;
            }
            else if (ROUTETODO == RouteTool.ROUTETODO_TO_ADDRESS)
            {
                toRoute = new DCRoutePoint();
                toRoute.street = street;
                toRoute.city = city;
                toRoute.country = country;
            }

            request.ExecutionOptions = new Carpool.Bing.Geocode.ExecutionOptions()
            {
                SuppressFaults = true
            };

            MainPage.main.KarpoCredentialsProvider.GetCredentials(credentials =>
            {
                // Pass in credentials for web services call.
                // Replace with your own Credentials.
                request.Credentials = credentials;

                // Make asynchronous call to fetch the data.
                try
                {
                    geocodeClient.GeocodeAsync(request);
                }
                catch
                {
                    KarpoMessageBox.showMessageBox("Failed to resolve the address!");
                }
            });
        }

        void client_GeocodeCompleted(object sender, GeocodeCompletedEventArgs e)
        {
            if (e.Result.ResponseSummary.StatusCode == Bing.Geocode.ResponseStatusCode.Success)
            {
                if (e.Result.Results.Count() > 0)
                {
                    Bing.Geocode.GeocodeResult res = e.Result.Results.ElementAt(0);
                    KarpoMessageBox.showMessageBox(res.Address.FormattedAddress);

                    Bing.Geocode.GeocodeLocation loc = res.Locations.ElementAt(0);

                    if (loc != null)
                    {

                        if (ROUTETODO == RouteTool.ROUTETODO_FROM_ADDRESS)
                        {
                            fromRoute.latitude = loc.Latitude;
                            fromRoute.longitude = loc.Longitude;
                            fromRoute.pointset = true;
                            fromRoute.street = res.Address.AddressLine;
                            fromRoute.postcode = res.Address.PostalCode;
                            addPushPin(routeFromPinCanvas, new GeoCoordinate(fromRoute.latitude, fromRoute.longitude), new Point(-10, -34));
                        }
                        else if (ROUTETODO == RouteTool.ROUTETODO_TO_ADDRESS)
                        {
                            toRoute.latitude = loc.Latitude;
                            toRoute.longitude = loc.Longitude;
                            toRoute.pointset = true;
                            toRoute.street = res.Address.AddressLine;
                            toRoute.postcode = res.Address.PostalCode;
                            addPushPin(routeToPinCanvas, new GeoCoordinate(toRoute.latitude, toRoute.longitude), new Point(-10, -34));
                        }
                        String fromaddress = "";
                        String toaddress = "";
                        if (fromRoute != null) fromaddress = fromRoute.street + ", " + fromRoute.postcode + " " + fromRoute.city;
                        if (toRoute != null) toaddress = toRoute.street + ", " + toRoute.postcode + " " + toRoute.city;

                        MainPage.main.setFromToAddress(fromaddress, toaddress);
                        MainPage.main.addresssetting.addresssettingPopup.IsOpen = false;


                    }
                    else
                    {
                        KarpoMessageBox.showMessageBox("Can not resolve the address.");
                    }
                    // Calculate the route
                    if (toRoute != null && fromRoute != null && toRoute.pointset && fromRoute.pointset)
                    {
                        CalculateRouteLatLon(fromRoute.latitude, fromRoute.longitude, toRoute.latitude, toRoute.longitude);
                    }
                    else if (loc != null)
                    {
                        KarpoMessageBox.hideMessageBox();
                        
                    }
                }
            }
            else
            {
                KarpoMessageBox.showMessageBox("client_GeocodeCompleted error: " + MapError.Reason(e));
            }

        }

        internal void SearchAddressForLatLon(double lat, double lon)
        {
            KarpoMessageBox.showMessageBox("Searching the address ...");

            GeocodeServiceClient geocodeClient = new GeocodeServiceClient();
            geocodeClient.ReverseGeocodeCompleted += new EventHandler<ReverseGeocodeCompletedEventArgs>(client_ReverseGeocodeCompleted);

            ReverseGeocodeRequest request = new ReverseGeocodeRequest();
            request.Culture = CultureInfo.CurrentUICulture.Name;

            request.Location = new Location();
            request.Location.Latitude = lat;
            request.Location.Longitude = lon;


            request.ExecutionOptions = new Carpool.Bing.Geocode.ExecutionOptions()
            {
                SuppressFaults = true
            };

            MainPage.main.KarpoCredentialsProvider.GetCredentials(credentials =>
            {
                // Pass in credentials for web services call.
                // Replace with your own Credentials.
                request.Credentials = credentials;

                // Make asynchronous call to fetch the data.
                try
                {
                    geocodeClient.ReverseGeocodeAsync(request);
                }
                catch 
                {
                    KarpoMessageBox.showMessageBox("Failed to resolve the address!");
                }
            });

        }

        void client_ReverseGeocodeCompleted(object sender, ReverseGeocodeCompletedEventArgs e)
        {
            if (e.Result.ResponseSummary.StatusCode == Bing.Geocode.ResponseStatusCode.Success)
            {
                if (e.Result.Results.Count() > 0)
                {
                    Bing.Geocode.GeocodeResult res = e.Result.Results.ElementAt(0);
                    KarpoMessageBox.showMessageBox(res.Address.FormattedAddress);

                    Bing.Geocode.GeocodeLocation loc = res.Locations.ElementAt(0);

                    if (res.Address != null)
                    {
                        String fromaddress = "";
                        String toaddress = "";
                      
                        if (ROUTETODO == RouteTool.ROUTETODO_FROM_POINT)
                        {
                            fromRoute.street = res.Address.AddressLine;
                            fromRoute.city = res.Address.Locality;
                            fromRoute.postcode = res.Address.PostalCode;
                            fromRoute.country = res.Address.CountryRegion;
                        }
                        else if (ROUTETODO == RouteTool.ROUTETODO_TO_POINT)
                        {
                            toRoute.street = res.Address.AddressLine;
                            toRoute.city = res.Address.Locality;
                            toRoute.postcode = res.Address.PostalCode;
                            toRoute.country = res.Address.CountryRegion;                            
                        }
                        if (fromRoute != null) fromaddress = fromRoute.street + ", " + fromRoute.postcode + " " + fromRoute.city;
                        if (toRoute != null) toaddress = toRoute.street + ", " + toRoute.postcode + " " + toRoute.city;

                        MainPage.main.setFromToAddress(fromaddress, toaddress);

                    }
                    else
                    {
                        KarpoMessageBox.showMessageBox("Can not resolve the address.");
                    }
                    // Calculate the route
                    if (toRoute != null && fromRoute != null)
                    {
                        CalculateRouteLatLon(fromRoute.latitude, fromRoute.longitude, toRoute.latitude, toRoute.longitude);
                    }
                    else if (res.Address != null)
                    {
                        KarpoMessageBox.hideMessageBox();
                    }
                }
            }
            else
            {
                KarpoMessageBox.showMessageBox("client_ReverseGeocodeCompleted error: " + MapError.Reason(e));
            }

        }

        internal void CalculateRouteLatLon(double latFrom, double lonFrom, double latTo, double lonTo)
        {
            KarpoMessageBox.showMessageBox("Calculating the route ...");

            RouteServiceClient client = new RouteServiceClient();
            client.CalculateRouteCompleted += new EventHandler<CalculateRouteCompletedEventArgs>(client_CalculateRouteLatLonCompleted);

            RouteRequest request = new RouteRequest();

            request.Culture = CultureInfo.CurrentUICulture.Name;

            // Don't raise exceptions.
            request.ExecutionOptions = new Carpool.Bing.Route.ExecutionOptions()
            {
                SuppressFaults = true
            };

            // Only accept results with high confidence.
            request.Options = new RouteOptions()
            {
                RoutePathType = RoutePathType.Points
            };

            Waypoint fromWaypoint = new Waypoint();
            fromWaypoint.Location = new Location();
            fromWaypoint.Location.Latitude = latFrom;
            fromWaypoint.Location.Longitude = lonFrom;

            Waypoint toWaypoint = new Waypoint();
            toWaypoint.Location = new Location();
            toWaypoint.Location.Latitude = latTo;
            toWaypoint.Location.Longitude = lonTo;

            request.Waypoints = new System.Collections.ObjectModel.ObservableCollection<Waypoint>();
            request.Waypoints.Add(fromWaypoint);
            request.Waypoints.Add(toWaypoint);

            MainPage.main.KarpoCredentialsProvider.GetCredentials(credentials =>
            {
                // Pass in credentials for web services call.
                // Replace with your own Credentials.
                request.Credentials = credentials;

                // Make asynchronous call to fetch the data.
                client.CalculateRouteAsync(request);

            });


        }



        void client_CalculateRouteLatLonCompleted(object sender, CalculateRouteCompletedEventArgs e)
        {
            KarpoMessageBox.hideMessageBox();

            if (e.Result.ResponseSummary.StatusCode == Bing.Route.ResponseStatusCode.Success)
            {

                routeModel = new LocationCollection();
                foreach (Location location in e.Result.Result.RoutePath.Points)
                {
                    routeModel.Add(location);
                }

                routePolyline.Locations = (LocationCollection)routeModel;
                if (!MainPage.mainmap.Children.Contains(routePolyline))
                {
                    MainPage.mainmap.Children.Add(routePolyline);
                }

                addPushPin(routeFromPinCanvas, routeModel.ElementAt(0), new Point(-10, -34));
                addPushPin(routeToPinCanvas, routeModel.ElementAt(routeModel.Count - 1), new Point(-10, -34));

                toRoute.distance = e.Result.Result.Summary.Distance;
                toRoute.traveltime = e.Result.Result.Summary.TimeInSeconds;

            }
            else
            {
                // Report route error.
                KarpoMessageBox.showMessageBox("client_CalculateRouteLatLonCompleted error: " + MapError.Reason(e));

            }
        }
    }



}

